using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace ObjectParser
{
	/// <summary>
	/// Summary description for AnimatorControl.
	/// </summary>
	public class AnimatorControl : System.Windows.Forms.PictureBox
	{
		private System.ComponentModel.IContainer components;
	
		public AnimatorControl()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
			if(playImage!=null)
				playImgPoint = new Point(this.Height/2-playImage.Height/2, 0);
			else
				playImgPoint=new Point(1,1);

			backBrush = new SolidBrush(this.BackColor);
			trackBrush = new SolidBrush(this.trackColor);
		}
		public delegate void FrameTick();
		public FrameTick OnFrameChange;
		public void CalcTimelineRect()
		{
			if(playImage==null)
			{
				timelineRect = new Rectangle(16, 0, this.Width-16, this.Height);
			}
			else
			{
				timelineRect = new Rectangle(playImgPoint.X+playImage.Width, 
					0, this.Width-playImgPoint.X-playImage.Width, this.Height);
			}
		}
		private Image playImage;
		public Image PlayImage
		{
			get
			{
				return playImage;
			}
			set
			{
				playImage = value;
				CalcTimelineRect();
			}
		}
		private int currentFrame=0;
		public int CurrentFrame
		{
			get
			{
				return currentFrame;
			}
			set
			{
				if(value>=0 && value<totalFrames)
					currentFrame = value;
				else
					currentFrame = 0;
			}
		}
		private int totalFrames=0;
		public int TotalFrames
		{
			get
			{
				return totalFrames;
			}
			set
			{
				if(value>=0)
					totalFrames = value;
				else
					totalFrames = 0;
			}
		}
		private float framesPerSec=1.0f;
		public float FramesPerSec
		{
			get
			{
				return framesPerSec;
			}
			set
			{
				if(value>0.0f)
					framesPerSec=value;
			}
		}

		private Point playImgPoint;
		private System.Windows.Forms.Timer timerAnimate;
		private Rectangle timelineRect;
		private SolidBrush backBrush, trackBrush;
		private Color trackColor=Color.FromArgb(0,255,0);
		public Color TrackColor
		{
			get
			{
				return trackColor;
			}
			set
			{
				trackColor=value;
				trackBrush=new SolidBrush(trackColor);
			}
		}
		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			this.timerAnimate = new System.Windows.Forms.Timer(this.components);
			// 
			// timerAnimate
			// 
			this.timerAnimate.Tick += new System.EventHandler(this.timerAnimate_Tick);
			// 
			// AnimatorControl
			// 
			this.BackColor = System.Drawing.SystemColors.InactiveCaptionText;
			this.Size = new System.Drawing.Size(200, 24);
			this.Click += new System.EventHandler(this.AnimatorControl_Click);
			this.SizeChanged += new System.EventHandler(this.AnimatorControl_SizeChanged);
			this.Paint += new System.Windows.Forms.PaintEventHandler(this.AnimatorControl_Paint);
			this.BackColorChanged += new System.EventHandler(this.AnimatorControl_BackColorChanged);

		}
		#endregion

        private int _sepWidth;
		private void AnimatorControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			e.Graphics.FillRectangle(backBrush, 0, 0, this.Width, this.Height);
			if(playImage!=null)
			{
				e.Graphics.DrawImage(playImage, playImgPoint);
			}
			if(totalFrames<=0)
			{
				if(timerAnimate.Enabled)
					e.Graphics.FillRectangle(Brushes.Black, timelineRect);
				else
					e.Graphics.FillRectangle(Brushes.Black, timelineRect);
			}
			else
			{
				//	Compute the point that cuts TimelineRect in half.
				_sepWidth = (int)((float)timelineRect.Width*(float)currentFrame/(float)totalFrames);
				//	The completed portion of the animation.
				e.Graphics.FillRectangle(trackBrush,
					timelineRect.Left, timelineRect.Top, _sepWidth, timelineRect.Height);
				//	The uncompleted portion of the animation.
				e.Graphics.FillRectangle(Brushes.Black,
					timelineRect.Left+_sepWidth, timelineRect.Top, 
					timelineRect.Width-_sepWidth, timelineRect.Height);
			}
		}

		private void AnimatorControl_SizeChanged(object sender, System.EventArgs e)
		{
			CalcTimelineRect();
		}
		private void timerAnimate_Tick(object sender, System.EventArgs e)
		{
			//	Advance frame
			if(currentFrame < totalFrames-1)
			{
				currentFrame++;
				this.Invalidate(timelineRect);
				if(OnFrameChange!=null)
					OnFrameChange();
			}
			//	Another frame is not possible.
			if(currentFrame == totalFrames-1)
				timerAnimate.Stop();
		}
		private void AnimatorControl_BackColorChanged(object sender, System.EventArgs e)
		{
			backBrush = new SolidBrush(this.BackColor);
		}

		private void AnimatorControl_Click(object sender, System.EventArgs e)
		{
			Point pt = this.PointToClient(Cursor.Position);
			//	Are we pushing the play/pause button?
			if(timelineRect.Left > pt.X)
			{
				if(timerAnimate.Enabled)
					timerAnimate.Stop();
				else
					timerAnimate.Start();
			}
			//	We are in the timeline rect.
			else
			{
				if(totalFrames>0)
				{
					//	Figure out where in the rect we are.
					pt.X-=timelineRect.Left;
					pt.Y-=timelineRect.Top;
					if(pt.X>=0 && pt.X<timelineRect.Width && pt.Y>=0 && pt.Y<=timelineRect.Height)
					{
						//	Compute the new frame
						float hLoc = (float)pt.X/(float)timelineRect.Width;
						int newFrame = (int)((float)totalFrames*hLoc);
						//	Check for an overflow
						if(newFrame>=totalFrames)
							newFrame = totalFrames-1;
						//	Change the frame
						if(newFrame!=currentFrame)
						{
							currentFrame = newFrame;
							this.Invalidate();
							if(OnFrameChange!=null)
								OnFrameChange();
						}
						//	Restart a time cycle if the timer is running
						if(timerAnimate.Enabled)
							timerAnimate.Start();
					}
				}
			}
		}
	}
}
